<?php
class Pageley_Gateway_Database_MySql_Tests extends Pageley_Test_Case implements Pageley_Domain_ReferenceValueProvider {

	private $gateway;
	private $articleType;
	private $categoryType;
	private $transaction;

	public function setUp() {
		$factory = Pageley_Config::getInstance();
        $factory->addConfigLocation("basic/attributes");
        $factory->addConfigLocation("basic/validators");
        $factory->addConfigLocation("logging");
        $factory->initialize();
        $namespace = new Pageley_Domain_BasicNamespace("urn:gateway.pageley.org:unit-tests", "mysql", "Pageley_MySQL_Tests");
		$string = new Pageley_Domain_Attribute_Basic("string");
		$money = $factory->valueOf("attribute.money");
		$timestamp = new Pageley_Domain_Attribute_Timestamp("timestamp");
		$this->categoryType = new Pageley_Domain_BasicType(
			$namespace,
			"Category"
		);
        $category = new Pageley_Domain_Attribute_Reference("category", $this->categoryType);
        $this->categoryType->setAttributes(
			new Pageley_Util_ArrayMap(array(
				"name" => $string,
                "parentCategory" => $category
			)));
		$this->articleType = new Pageley_Domain_BasicType(
			$namespace,
			"Article",
			new Pageley_Util_ArrayMap(array(
				"name" => $string,
				"price" => $money,
                "category" => $category,
				"dateCreated" => $timestamp
			))
		);
		$this->gateway = new Pageley_Gateway_Database(new Pageley_Gateway_Database_MySql_DataSource(
			"localhost", "3306", "pageley_mysql", "pageley_mysql"), "pageley_mysql_tests", false);
		$this->transaction = $this->gateway->getTransaction();
	}

	public function testInsert() {
		$category = $this->categoryType->newInstance();
		$category->set("name", "Sprays");
        $category->setId(1);
		$this->gateway->insert($category);
		
        $article = $this->articleType->newInstance();
		$article->set("name", "Cobra spray");
		$article->set("price", new Pageley_Basic_Domain_Money(
			Pageley_Basic_Domain_Currency::$EUR, 7.5));
		$article->set("category", $category);
		$dateCreated = Pageley_Util_Timestamp::parse("2008-01-01 12:00:00");
		$article->set("dateCreated", $dateCreated);
		$this->gateway->insert($article);
		$this->assertEquals(1, $article->getId());
		
		$article = $this->gateway->find($this->articleType, 1);
		$this->assertNotNull($article);
		$this->enableReferences($article);
		$this->assertEquals(7.5, $article->get("price")->get("value"));
		$this->assertEquals($dateCreated, $article->get("dateCreated"));
		$this->assertEquals($category, $article->get("category"));
	}

	public function testQuery() {
	    $this->insertData();
		
        $category = $this->categoryType->newInstance();
        $category->setId(1);
		$articles = $this->gateway->query(
			new Pageley_Query_Basic($this->articleType, new Pageley_Query_Condition_AndGroup(
            new Pageley_Util_ArrayMap(array(
                new Pageley_Query_Condition_GreaterThan("price.value", 2.5),
                new Pageley_Query_Condition_LessThan("price.value", 5.0),
                new Pageley_Query_Condition_Equals("category", $category)
            )))));
		$this->assertEquals(1, $articles->size());
		$article = $articles->get(0);
		$this->assertNotNull($article);
		$this->enableReferences($article);
		$this->assertEquals(2, $article->getId());
		$this->assertEquals(3.0, $article->get("price")->get("value"));
		$this->assertEquals(Pageley_Util_Timestamp::parse("2008-01-01 12:00:00"), $article->get("dateCreated"));
		$this->assertEquals(1, $article->get("category")->getId());
	}

	public function testCount() {
        $this->insertData();
        
		$category = $this->categoryType->newInstance();
        $category->setId(1);
		$count = $this->gateway->count(
			new Pageley_Query_Basic($this->articleType, new Pageley_Query_Condition_AndGroup(
            new Pageley_Util_ArrayMap(array(
                new Pageley_Query_Condition_GreaterThan("price.value", 2.5),
                new Pageley_Query_Condition_Equals("category", $category)
            )))));
		$this->assertEquals(2, $count);
	}
	
	private function insertData() {
        $category = $this->categoryType->newInstance();
        $category->set("name", "Sprays");
        $category->setId(1);
        $this->gateway->insert($category);
        
        $dateCreated = Pageley_Util_Timestamp::parse("2008-01-01 12:00:00");
        $article = $this->articleType->newInstance();
        $article->set("name", "Llama spray");
        $article->set("price", new Pageley_Basic_Domain_Money(
            Pageley_Basic_Domain_Currency::$EUR, 1.5));
        $article->set("category", $category);
        $article->set("dateCreated", $dateCreated);
        $this->gateway->insert($article);
        
        $article = $this->articleType->newInstance();
        $article->set("name", "Frog spray");
        $article->set("price", new Pageley_Basic_Domain_Money(
            Pageley_Basic_Domain_Currency::$EUR, 3.0));
        $article->set("category", $category);
        $article->set("dateCreated", $dateCreated);
        $this->gateway->insert($article);
        
        $article = $this->articleType->newInstance();
        $article->set("name", "Cobra spray");
        $article->set("price", new Pageley_Basic_Domain_Money(
            Pageley_Basic_Domain_Currency::$EUR, 7.5));
        $article->set("category", $category);
        $article->set("dateCreated", $dateCreated);
        $this->gateway->insert($article);
	}

	public function testDelete() {
		$category = $this->categoryType->newInstance();
		$category->set("name", "Sprays");
        $category->setId(1);
		$this->gateway->insert($category);
		
        $article = $this->articleType->newInstance();
		$article->set("name", "Cobra spray");
		$article->set("price", new Pageley_Basic_Domain_Money(
			Pageley_Basic_Domain_Currency::$EUR, 7.5));
		$article->set("category", $category);
		$dateCreated = Pageley_Util_Timestamp::parse("2008-01-01 12:00:00");
		$article->set("dateCreated", $dateCreated);
		$this->gateway->insert($article);
		
		$article = $this->gateway->find($this->articleType, 1);
		$this->assertNotNull($article);
		$this->enableReferences($article);
		$this->gateway->delete($article);
		$article = $this->gateway->find($this->articleType, 1);
		$this->assertNull($article);
	}

	public function testUpdate() {
		$category = $this->categoryType->newInstance();
		$category->set("name", "Sprays");
        $category->setId(1);
		$this->gateway->insert($category);
		
        $article = $this->articleType->newInstance();
		$article->set("name", "Cobra spray");
		$article->set("price", new Pageley_Basic_Domain_Money(
			Pageley_Basic_Domain_Currency::$EUR, 7.5));
		$article->set("category", $category);
		$dateCreated = Pageley_Util_Timestamp::parse("2008-01-01 12:00:00");
		$article->set("dateCreated", $dateCreated);
		$this->gateway->insert($article);
		
		$article = $this->gateway->find($this->articleType, 1);
		$this->assertNotNull($article);
		$this->enableReferences($article);
		$article->set("price", new Pageley_Basic_Domain_Money(
			Pageley_Basic_Domain_Currency::$EUR, 3.9));
		$this->gateway->update($article);
		$article = $this->gateway->find($this->articleType, 1);
		$this->assertEquals(3.9, $article->get("price")->get("value"));
	}

	public function tearDown() {
		$this->transaction->rollback();
	}

	public function onFail() {
		$this->transaction->rollback();
	}
	
	public function find($type, $id) {
		return $this->gateway->find($type, $id);
	}
	
    private function enableReferences($entity) {
        foreach($entity->getType()->getAttributes() as $propertyName => $attribute) {
            if($attribute->isReference()) {
                $property = $entity->getProperty($propertyName);
                $property->setValueProvider($this);
            }
        }
    }
}
